/**
 * 描述:Es
 *  1.为什么说es是近实时的搜索引擎
 *      1.fsync落盘：数据写入es时，通常是先将数据存入虚拟文件系统，也就是内存里，然后调用fsync才能把虚拟文件系统里面的数据落入磁盘。
 *        这样做的原因是防止掉电的时候，数据丢失
 *      2.segment：elastic是采用lucene这个库来实现倒排索引的，使用segment分段来存储数据，用commit point来记录所有segment的元数据
 *        一条数据要被搜索到，必须写入segment中
 *      3.translog：es使用translog来记录所有的操作，新增一条记录的时候，es会把数据写到translog和内存缓冲区中
 *        translog是顺序写的，实时的fsync，性能很高，只要数据写入了translog，就代表落盘了，保证了可靠性
 *        每隔5秒钟会把translog刷新(fsync)到磁盘中,也就是说系统掉电的情况下es最多会丢失5秒钟的数据
 *      4.内存缓冲区：内存缓冲区和translog是es近实时的关键，因为数据是直接写入到translog落盘的，但是想要数据能被查询到，必须写入segment，
 *        需要手动调用refresh操作
 *      5.refresh：默认情况下，es每隔一秒钟执行一次refresh，可以通过参数index.refresh_interval来修改这个刷新间隔
 *          1.所有内存缓冲区中的文档，写入到一个新的segment中，但是没有调用fsync，数据可能丢失
 *          2.segment被打开，使得里面得文档能被搜索到
 *          3.清空内存缓冲区
 *      6.近实时得原因：内存缓冲区的数据，被写入 segment 文件，且 segment 文件被写入虚拟文件系统后，才能打开这个新 segment 文件，以被检索到。
 *        因此在新的segment文件形成前，内存缓冲区里得数据是无法被检索到的。而refresh操作，默认是1s，也就说新插入的数据1s后才能被检索到
 *      7.flush:清空translog，虚拟文件系统中的段文件 fsync 刷盘
 *          1.把所有在内存缓冲区中的文档写入到一个新的segment中
 *          2.清空内存缓冲区
 *          3.往磁盘里写入commit point信息
 *          4.虚拟文件系统的page cache(segments) fsync到磁盘
 *          5.删除旧的translog文件，因此此时内存中的segments已经写入到磁盘中,就不需要translog来保障数据安全了
 *      8.flush和fsync的区别：flush是把内存中的数据(包括translog和segments)都刷到磁盘,而fsync只是把translog刷新的磁盘(确保数据不丢失)
 *      9.es因为refresh机制，导致近实时的查询，会延迟1s左右；因为translog的机制，如果数据丢失，最多会丢失5s的数据
 *
 *  2.es核心概念与架构
 *      1.索引index：类似mysql的表，一个索引里面存储的是要查询的数据
 *      2.类型type：7以前可以定义类型，并且根据类型去查询。7以后就没有类型的概念了
 *      3.文档document：一个文档就是一条数据，索引中存储了很多文档，是JSON格式的
 *      4.字段Field：相当于表结构的意思
 *      5.映射mapping:定义某个字段的数据类型、默认值、分析器、是否被索引等等
 *      6.分片shards：一个索引可以存储超过单个节点磁盘大小的数据，或者单个节点处理搜索请求，响应太慢。所以引入了分片机制，
 *        将一个索引划分成了多份，每一份称为分片。当创建索引的时候可以指定分片数量，每个分片也是一个功能完善且独立的“索引”
 *          1.允许水平分割、扩展存储（有点像redis-cluster结构）
 *          2.允许在分片上进行分布式并行的操作，进而提高性能、吞吐量
 *      7.副本replices：在一个网络环境中，失败随时可能发生，如果某个分片、节点突然挂了，就需要一个故障转移机制，所以es允许创建副本。
 *        一份或多份，创建索引的时候可以设置，副本存储在不同的分片中
 *          1.在节点挂了的情况下，提高高可用。复制分片不能跟主分片处于同一台节点中，不然无法保证高可用
 *          2.扩展搜索量/吞吐量，因为搜索可以在副本上并行运行（跟redis-cluster不一样，跟redis从节点一样）
 *  3.es写入数据流程
 *      1.客户端随机选择一个es集群的节点，发送请求，被选择的节点称为协调节点
 *      2.协调节点查询集群状态信息并计算路由，将请求发送到真正处理请求的节点（主分片所在的节点）
 *      3.包含主分片的节点写入请求，并且将数据同步到包含副本分片的节点
 *          1.数据先写入buffer(内存缓冲区)中，在buffer中数据是搜索不到的；同时将数据写入translog日志文件中，保证不丢失
 *          2.当buffer达到一定的阈值（如果没数据，不会触发），或者一定时间（默认1s），就会触发refresh，将buffer中的数据写入到一个新的segment中，
 *            但是此时这个segment不是磁盘文件，而是先存入os cache。存入后清空buffer。
 *          3.数据一写入操作系统缓存，就可以被检索到了。近实时的原因，1s的时差
 *          4.文件缓存系统在translog的数据量达到512M或者30分钟时，会触发一次flush，将数据刷入磁盘，然后清除translog
 *      4.协调节点收到包含主分片节点的响应信息，将结果返回给客户端
 *  4.es读取数据流程
 *      1.客户端随机选择es集群中的一个节点，并且发送请求，被选择的节点称为协调节点
 *      2.协调节点查询集群状态信息并且使用round-robin算法计算出此次请求的节点，将请求发送到真正处理请求的节点（主分片节点和副本节点随机分配）
 *      3.处理读请求的节点将数据返回给协调节点
 *      4.协调节点会把文档信息返回给client
 *  5.es检索数据的流程（检索是带条件的查询，读取是不带条件的get请求）
 *      1.客户端发送请求到一个协调节点
 *      2.协调节点将搜索请求转发给所有的分片对应的主分片或者副本分片
 *      3.每个分片分片将自己的搜索结果（doc_id），返回给协调节点，由协调节点进行数据的合并、排序、分页等操作，产出最终结果
 *      4.接着协调节点，根据doc_id去各个节点上拉取实际的document数据，返回给客户端（注意分页查询，当from特别大的时候会
 *      造成大量无用的数据返回给协调节点，谨慎使用）
 *  6.es参数优化：
 *      1.增加refresh的时间间隔
 *          1.为提高索引性能，es写入数据的时候采用延迟写入的策略，数据先写入内存中，当超过默认1s会进行一次refresh，将内存中的segment数据刷新
 *            到操作系统中，我们才能搜索数据。
 *          2.当我们对数据的时效性要求不高的话，可以将refresh的时间间隔设置长一点或者设置为-1关闭refresh，等数据索引完毕再开启来。
 *          3.参数：index.refresh_interval
 *      2.减少副本数量
 *          1.es7创建索引默认是五个主分片，一个副本，这样会提高集群高可用，提高并发，但是会影响写入效率。因为segment合并的操作在副本分片上也需要进行，
 *          2.如果做搜索业务，还是建议副本设置为3个（看节点情况），但是如果是存储日志或者互联网舆情数据，允许数据有一定的丢失，可以只设置1个。
 *          3.如果是构建索引插入数据或者reindex的时候，可以先设置为0，后面再恢复预定义的大小
 *      3.设置es堆内存，默认是1G，如果节点只部署es，64G内存的话，可以设置成31G，并且确保最小堆内存和最大堆内存相同，防止程序运行时改变堆内存大小。
 *          1.为什么不设置的更大：jvm在内存小于32G的时候会采用一个内存对象指针压缩技术，因为这个，其实如果设置的40G也跟32G差不多
 *      4.禁止swap：swap是内存和磁盘的交换，影响io和读写速度，，通过bootstrap.memory_lock:true锁定内存。
 *      5.修改translog参数，异步更新：
 *          1.es为了保证数据不丢失，采用顺序写记录translog文件到磁盘，如果不在意这种丢失，可以设置
 *          2.index.translog.durability:async    异步刷写
 *          3.index.translog.sync_interval:120s  sync时间间隔提高
 *      6.修改flush的大小：
 *          1.flush的主要目的是把文件缓存系统中的段持久化到磁盘，当translog的数据量达到512M或者30分钟的时候，会触发一次flush
 *          2.可以加大，让文件缓存系统存储更多的数据
 *          3.index.translog.flush_threshold_size:512M
 *      7.磁盘，es是重度使用磁盘，磁盘的吞吐量越大，性能越好，节点越稳定：
 *          1.使用SSD
 *          2.如果SSD不够（因为比较贵），可以冷热数据分离，热数据，比如最近的数据放SSD，冷数据放普通磁盘
 *      8.控制分片数
 *          1.分片数的配置，是无法后期修改的，所以需要前期就规划好
 *          2.理论上500G的索引，分片数在16个这样，但是还是需要考虑节点的数量
 *          3.如果分片数远远大于节点数量，那么就无法保证高可用了，会导致一个节点上存在多个分片，所以一般分片数的设置不超过节点数的三倍
 *  7.es查询优化：
 *      1.scroll查询：如果要查询大数据量的话，最好避免直接查询，使用scroll翻滚查询，再聚合查询结果
 *      2.自动生成id：如果不是业务上的强要求，尽量使用es自己生成id，如果使用特定id，es会检查对应的索引下是否存在相同id，
 *        随着文档越来越大，消耗也会越来越大
 *      3.少使用nested：创建索引的时候尽量少使用nested类型，并且保证nested类型的字段不能过多，一个document，每一个nested都会生成一个
 *        独立的document，影响查询效率，尤其是join的
 *      4.批量插入数据使用bulk，bulk默认设置批量提交的数据量不能超过100M
 *  8.es选举流程
 *      1.Elasticsearch的集群选主是通过ZenDiscovery模块负责的，主要包含Ping（节点之间通过这个RPC来发现彼此）和Unicast（单播模块包含
 *        一个主机列表以控制哪些节点需要ping通）这两部分
 *          1.ZenDiscory：es自己实现的一套用于节点发现和选主功能的模块
 *          2.依赖以下配置发现节点：discovery.zen.ping.unicast.hosts: [1.1.1.1, 1.1.1.2, 1.1.1.3]
 *      2.对所有可以成为master的节点(node.master:true)根据nodeId字典排序，每次选举每个节点都把自己知道的所有节点排一次序，
 *        然后选出第一个（第0位）节点，暂定它为master节点
 *      3.如果对某个节点的投票数达到一定的值（可以成为master节点数 n/2 + 1，节点可以选择自己），那这个节点就是master。
 *        否则重新选举一直到满足上述条件
 *      4.master节点的职责主要包括集群、节点和索引的管理，不负责文档级别的管理；data节点可以关闭http功能
 *  9.es集群脑裂问题
 *      1.产生原因
 *          1.网络问题：集群间的网络延迟导致一些节点访问不到 master，认为 master 挂掉了从而选举出新的master，并对 master 上的分片和副本标红，
 *            分配新的主分片
 *          2.节点负载：主节点的角色既为 master 又为 data，访问量较大时可能会导致 ES 停止响应造成大面积延迟，此时其他节点得不到主节点的响应认为主节点挂掉了，
 *            会重新选取主节点
 *          3.内存回收：data 节点上的 ES 进程占用的内存较大，引发 JVM 的大规模内存回收，造成 ES 进程失去响应
 *      2.解决方案
 *          1.减少误判：discovery.zen.ping_timeout节点状态的响应时间，默认3s，如果master在3s内未应答，一般认为是挂了，可以
 *            调大参数为 6s，可适当减小误判
 *          2.选举触发： discovery.zen.minimum_master_nodes:1。该参数是用于控制选举行为发生的最小集群主节点数量。当备选主节点的个数大于该参数的值
 *            且备选主节点中有该参数个节点认为主节点挂了，则进行选举。最好设置成多数原则，比如你有五个候选主节点，设置为(n / 2 + 1)，设置为3
 *  10.项目中如何使用es的？
 *      1.业务：项目中一般存储企业信息，企业变更信息，企业的各类关联数据。或者存储舆情数据，就是互联网爬虫爬取的网络上的头条数据等等
 *      2.数据量：看业务吧，企业是近千万家，包含企业的各类变更法人信息等，舆情数据是亿级的，每日入库千万级数据，保留近两个月的数据
 *      3.集群大小：不同业务集群也不同，一般是三台集群，内存64G，磁盘单台4T
 *      4.优化：企业数据比较侧重于并发读，每日写入不大，但是对数据的可靠性可用性要求高，互联网舆情数据比较侧重于并发写，每日写入量大，但是查询较少，而且允许数据丢失，
 *        两种的优化也不一样。
 *          1.舆情数据优化，侧重于写入的，一般对集群的一些参数进行优化：
 *              1.增加refresh的时间间隔，默认是1s，一般开到30s
 *              2.减少副本数量：es默认为1个，有时候不设置副本或者设置1个，看数据，因为丢失了可以再次爬取，但是设置副本占据的数据量太大了，导致磁盘不够用
 *              3.设置es的堆内存，64G的机器，设置为31G，而且最大最小堆内存要设置成一样，避免内部加大内存的消耗
 *              4.禁止swap：swap是内存和磁盘的交换，要是发生了会导致卡顿，一般设置锁定内存的参数
 *              5.修改translog的参数：translog是es防止数据丢失的一种策略，可以设置异步刷新到磁盘，而且可以设置的大一点，flush的时间也可以设置的久一点
 *          2.企业数据优化，侧重于读取的，一般是对查询的一些优化，分区和副本数
 *              1.设置分区：三台节点的话，分区最大不应该超过节点数的两倍，所以分区设置为6
 *              2.设置副本：副本数设置为3，保证并发查询和可用性
 *              3.查询优化
 *                  1.scroll查询：如果要查询大数据量的话，最好避免直接查询，使用scroll翻滚查询，再聚合查询结果
 *                      1.如果直接使用es的分页，页数越多，会造成大量数据发送到协调节点进行合并和过滤
 *                  2.自动生成id：如果不是业务上的强要求，尽量使用es自己生成id，如果使用特定id，es会检查对应的索引下是否存在相同id，随着文档越来越大，消耗也会越来越大
 *                  3.少使用nested：创建索引的时候尽量少使用nested类型，并且保证nested类型的字段不能过多，一个document，每一个nested都会生成一个独立的document，
 *                    影响查询效率，尤其是join的
 *                  4.批量插入数据使用bulk，bulk默认设置批量提交的数据量不能超过100M
 *  11.es大数据量查询下的优化（数十亿）
 *      1.可能产生的问题：搜索的时候，突然来了卡顿，等5-10s才返回，然后后面的查询又快了
 *      2.filesystem cache
 *          1.es查询数据都是查询文件系统缓存的，会将磁盘中的数据加入到文件系统缓存去，所以需要足够大的filesystem cache
 *          2.性能差距是秒级和毫秒级的差距，走纯内存的非常快
 *          3.所以如果你仅仅需要查询es的name,age,这两个字段，却把document的另外30个字段都加载进文件系统缓存了，那占据太大空间，就没地方放更多的数据了
 *          4.所以一般会将数据存放在hbase中，然后将需要查询的字段放到es中，es查询完了再去hbase中根据id查询，做到毫秒级的响应
 *      3.数据预热
 *          1.可以用定时任务，将热点数据拿去查询，刷新到文件系统缓存中，加速查询的速度，可以做一个专门的预热子系统
 *      4.冷热数据分离
 *          1.可以热数据占据一个索引，冷数据一个索引，定期将热数据同步到冷数据中，热数据就用来预热
 *
 * @author Madison You
 * @created 22:27
 */
public class Elasticsearch {
}
